home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / dsp / 56ktools / dspkgctr.z / dspkgctr / gcc / config / out-mips.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-08  |  12.1 KB  |  525 lines

  1. /* Subroutines for insn-output.c for MIPS
  2.    Contributed by A. Lichnewsky, lich@inria.inria.fr.
  3.    Copyright (C) 1989 Free Software Foundation, Inc.
  4.  
  5.    $Id: out-mips.c,v 1.1 90/10/29 11:03:41 jeff Exp $
  6.  
  7. This file is part of GNU CC.
  8.  
  9. GNU CC is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 1, or (at your option)
  12. any later version.
  13.  
  14. GNU CC is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with GNU CC; see the file COPYING.  If not, write to
  21. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  22.  
  23.  
  24. #include <stdio.h>
  25. extern void  my_print_rtx ();
  26. extern void  abort_with_insn ();
  27.  
  28.  
  29. /* Global variables for machine-dependent things.  */
  30.  
  31. char *reg_numchar[] = REGISTER_NUMCHAR;
  32.  
  33. /* When eliminating the frame pointer, this is the size of the frame
  34.    aside from explicit stack slots.  */
  35. int frame_stack_difference;
  36.  
  37. /* Return truth value of whether OP can be used as an operands
  38.    where a 16 bit integer is needed  */
  39.  
  40. int
  41. arith_operand (op, mode)
  42.      rtx op;
  43.      enum machine_mode mode;
  44. {
  45.   return (register_operand (op, mode)
  46.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  47. }
  48.  
  49. /* Return truth value of whether OP can be used as an operand in a two
  50.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  51.  
  52. int
  53. arith32_operand (op, mode)
  54.      rtx op;
  55.      enum machine_mode mode;
  56. {
  57.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  58. }
  59.  
  60. /* Return truth value of whether OP is a integer which fits in 16 bits  */
  61.  
  62. int
  63. small_int (op, mode)
  64.      rtx op;
  65.      enum machine_mode mode;
  66. {
  67.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  68. }
  69.  
  70.  
  71. #if 0
  72.                 /* Used to allow constant expression known
  73.                 ** only at assembly time
  74.                 */
  75. int
  76. legitimize_constant_expr(expr)
  77.      rtx expr;
  78. {
  79.   if (GET_CODE (expr) == PLUS
  80.       ||
  81.       GET_CODE (expr) == MINUS)
  82.     return (BASIC_CONSTANT_P (XEXP (expr, 0))
  83.         && BASIC_CONSTANT_P (XEXP (expr, 1)));
  84.   return 0;
  85. }
  86. #endif
  87.  
  88. char *
  89. output_load_immediate (operands)
  90.      rtx *operands;
  91. {
  92.   rtx xops[3];
  93.   xops[0] = operands[0];
  94.   xops[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]));
  95.  
  96.   if ((INTVAL (operands[1]) >> 16)
  97.       && (INTVAL (operands[1]) & 0xffff))
  98.     {
  99.       if (!((-INTVAL (operands[1])) >> 16))
  100.     {
  101.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  102.                  (INTVAL (operands[1])) & 0xffff);
  103.       output_asm_insn ("addi%:\t%0,$0,%x1\t#movsi low part of %2",
  104.                xops);
  105.     }
  106.       else
  107.     {
  108.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  109.                  (INTVAL (operands[1]))>>16);
  110.       output_asm_insn ("lui\t%0,%x1\t#movsi high part of %2", xops);
  111.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  112.                  (INTVAL (operands[1])) & 0xffff);
  113.       output_asm_insn ("ori\t%0,%x1\t#movsi low part of %2", xops);
  114.     }
  115.     }
  116.   else if (INTVAL (operands[1]) >> 16)
  117.     {
  118.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  119.              (INTVAL (operands[1]))>>16);
  120.       output_asm_insn ("lui\t%0,%x1\t#movsi high part of %2", xops);
  121.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  122.              (INTVAL (operands[1])) & 0xffff);
  123.     }
  124.   else
  125.     {
  126.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  127.              (INTVAL (operands[1])) & 0xffff);
  128.       output_asm_insn ("ori\t%0,$0,%x1\t#movsi low part of %2",
  129.                xops);
  130.     }
  131.   return "";
  132. }
  133.  
  134.                 /* Used to obtain address of subregs      */
  135.                 /* when in memory. This takes mode and    */
  136.                 /* subreg number into account             */
  137.  
  138. rtx
  139. addr_compensate (addr, submode, origmode, subnum)
  140.      rtx addr;
  141.      enum machine_mode submode;
  142.      enum machine_mode origmode;
  143.      int subnum;
  144. {
  145.   extern rtx change_address ();
  146.   extern rtx plus_constant ();
  147.  
  148.   if (submode == QImode && origmode == SImode)
  149.     {
  150. #ifdef BYTES_BIG_ENDIAN
  151.       return change_address (addr, QImode,
  152.                  plus_constant (XEXP (addr, 0), 3 - subnum));
  153. #else
  154.       return change_address (addr, QImode,
  155.                  plus_constant (XEXP (addr, 0), subnum));
  156. #endif
  157.     }
  158.   else if (submode == HImode && origmode == SImode)
  159.     {
  160. #ifdef BYTES_BIG_ENDIAN
  161.       return change_address (addr, HImode,
  162.                  plus_constant (XEXP (addr, 0), 2 - 2*subnum));
  163. #else
  164.       return change_address (addr, HImode,
  165.                  plus_constant (XEXP (addr, 0), subnum));
  166. #endif
  167.     }
  168.   else
  169.     abort_with_insn (addr, "addr_compensate does not support mode");
  170. }
  171.  
  172.  
  173.  
  174.  
  175.                 /* VARARGS */
  176. int function_suspect;
  177. int varargs_suspect = 0;
  178. int this_varargs_suspect;
  179.  
  180.                 /* PARAMETER LIST CONSTRUCTION */
  181.  
  182.  
  183. static struct
  184. {
  185.   enum arg_state nxs_if_f, nxs_if_g;
  186.   short reg_if_f, reg_if_g;
  187. }
  188.   arg_state_table[(int) (ARG_STA_GGGG + 1)]  = ARG_STA_AUTOMA;
  189.  
  190.  
  191.  
  192.                 /* For use in Frame/ Stack pointer management*/
  193. char * current_function_name;
  194. int current_function_total_framesize;
  195. typedef CUMULATIVE_ARGS cumulative_args;
  196.  
  197. enum arg_state
  198. function_arg_advance (cum, mode, type)
  199.      cumulative_args *cum;
  200.      enum machine_mode mode;
  201.      int type;
  202. {
  203.   cum->arg_rec_state
  204.     = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
  205.        ? arg_state_table[(int)((cum->arg_rec_state))].nxs_if_f
  206.        : arg_state_table[(int)((cum->arg_rec_state))].nxs_if_g);
  207.  
  208.   (cum->arg_num)++;
  209. }
  210.  
  211. rtx
  212. function_arg (cum, mode, type, named)
  213.      cumulative_args *cum;
  214.      enum machine_mode mode;
  215.      int type;
  216.      int named;
  217. {
  218.   int regnum;
  219.  
  220.   regnum
  221.     = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
  222.        ? arg_state_table[(int)((cum->arg_rec_state))].reg_if_f
  223.        : arg_state_table[(int)((cum->arg_rec_state))].reg_if_g);
  224.  
  225.   if (mode == BLKmode)
  226.     return 0;
  227.   else if (regnum >= 0)
  228.     return gen_rtx (REG, mode, regnum);
  229.   else if (regnum == -2)
  230.     {
  231.       if (mode == SFmode)
  232.     return gen_rtx (SUBREG, SFmode, gen_rtx (REG, DFmode, 6), 0);
  233.       else
  234.     return gen_rtx (REG, DFmode, 6);
  235.     }
  236.   else
  237.     return 0;
  238. }
  239.  
  240.  
  241.  
  242. static  rtx branch_cmp_op[2];
  243. static  enum machine_mode branch_cmp_mode;
  244.  
  245. compare_collect (mode, op0, op1)
  246.      enum machine_mode mode;
  247.      rtx op0;
  248.      rtx op1;
  249. {
  250.   if (TARGET_DEBUGD_MODE)
  251.     {
  252.       fprintf (stderr, "compare_collect mode = %d, operands::", mode);
  253.       my_print_rtx (op0);
  254.       my_print_rtx (op1);
  255.     }
  256.   branch_cmp_op[0] = op0;
  257.   branch_cmp_op[1] = op1;
  258.   branch_cmp_mode = mode;
  259. }
  260.  
  261.  
  262. compare_restore (operands, mode, insn)
  263.      rtx *operands;
  264.      enum machine_mode *mode;
  265.      rtx insn;
  266. {
  267.   rtx  previous;
  268.   rtx  prev_par;
  269.   if (TARGET_DEBUGD_MODE)
  270.     {
  271.       fprintf (stderr, "compare_restore returning mode = %d, operands:%X,%X:",
  272.            branch_cmp_mode, branch_cmp_op[0], branch_cmp_op[1]);
  273.       my_print_rtx (branch_cmp_op[0]);
  274.       my_print_rtx (branch_cmp_op[1]);
  275.     }
  276.  
  277.   if ((! branch_cmp_op[0]) && (! branch_cmp_op[1]))
  278.     {
  279.       /*  Signal that multiple branches following */
  280.       /* a comparison have been found             */
  281.       if (TARGET_DEBUGD_MODE)
  282.     {
  283.       fprintf (stderr, "Not at ease in compare_restore\n");
  284.       my_print_rtx (insn);
  285.       my_print_rtx (PREV_INSN (insn));
  286.     }
  287.       /*  Find the previous comparison */
  288.       while ((GET_CODE (PREV_INSN (insn))) == JUMP_INSN)
  289.     {
  290.       insn = PREV_INSN (insn);
  291.       if (TARGET_DEBUGD_MODE)
  292.         my_print_rtx (PREV_INSN (insn));
  293.     }
  294.  
  295.       previous =  PATTERN (PREV_INSN (insn));
  296.  
  297.       if ((GET_CODE (previous)) == PARALLEL)
  298.     {
  299.       /*  Signal  that we have a very strange */
  300.       /* RTL construct,... usually generated  */
  301.       /* by the optimizer, that seems to      */
  302.       /* contradict the documentation         */
  303.  
  304.       /* However, this construct holds the    */
  305.       /* correct information in a very reliable */
  306.       /* way */
  307.  
  308.       branch_cmp_op[0] = XVECEXP (previous, 0, 0);
  309.       branch_cmp_op[1] = XVECEXP (previous, 0, 1);
  310.       /*       warning ("Check branch optimization with -mdebugd");
  311.        */
  312.     }
  313.       else
  314.     if (((GET_CODE (previous)) == SET)
  315.         &&
  316.         ((GET_CODE (XEXP (previous, 0))) == CC0)
  317.         &&
  318.         ((GET_CODE (XEXP (previous, 1))) == COMPARE))
  319.       {            /* Here we find the comparison info    */
  320.         /* in a more classical format          */
  321.  
  322.         previous = XEXP (previous, 1);
  323.         branch_cmp_op[0] = XEXP (previous, 0);
  324.         branch_cmp_op[1] = XEXP (previous, 1);
  325.       }
  326.           else
  327.       {            /* Be prepared for other things popping out */
  328.         abort ();
  329.       }
  330.     }
  331.  
  332.  
  333.  
  334.   if (!  branch_cmp_op[0])
  335.     operands[0] = gen_rtx (REG, VOIDmode, 0);
  336.   else
  337.     operands[0] = branch_cmp_op[0];
  338.   if (!  branch_cmp_op[1])
  339.     operands[1] = gen_rtx (REG, VOIDmode, 0);
  340.   else
  341.     operands[1] = branch_cmp_op[1];
  342.   *mode = branch_cmp_mode;
  343.  
  344.   branch_cmp_op[0] = NULL;
  345.   branch_cmp_op[1] = NULL;
  346.  
  347. }
  348.  
  349. #if 0
  350.                 /* See flags.h and toplev.c */
  351. extern int optimize;
  352. extern int flag_combine_regs;
  353. extern int flag_strength_reduce;
  354. extern int flag_no_peephole;
  355. extern int flag_inline_functions;
  356. extern int flag_omit_frame_pointer;
  357. extern char *main_input_filename;
  358. extern char *asm_file_name;
  359.                 /* See c-tree.h  and c-decl.c */
  360. extern int flag_signed_char;
  361.  
  362. #include <time.h>
  363. #include <sys/types.h>
  364. #include <sys/timeb.h>
  365.  
  366. void
  367. print_options (out)
  368.      FILE *out;
  369. {
  370.   char *a_time;
  371.   long c_time;
  372.  
  373.   fprintf (out, " #OPTIONS:\t%s%s%s%s%s%s%s\n",
  374.        (TARGET_NOFIXED_OVFL ? " -dnofixed-ovfl":" -dfixed-ovfl"),
  375.        (optimize ? " optimize" : ""),
  376.        (flag_combine_regs ? " -fcombine-regs" : " !combine-regs"),
  377.        (flag_strength_reduce ? "" : " !strength_reduce"),
  378.        (flag_omit_frame_pointer ?"" :" !omit_frame_pointer"),
  379.        (flag_no_peephole ? "" : " peephole"),
  380.        (flag_inline_functions ?" inline-functions":""));
  381.   fprintf (out, " #OPTIONS:\t%s%s\n",
  382.        (flag_signed_char ? " signed-char" : " !signed-char"),
  383.        (TARGET_GP_OPT    ? " gpOPT"      : " !gpOPT"));
  384.   fprintf (out, " #Source:\t%s\n", main_input_filename);
  385.   fprintf (out, " #Destination:\t%s\n", asm_file_name);
  386.   c_time = time (0);
  387.   a_time = ctime (&c_time);
  388.   fprintf (out, " #Compiled:\t%s", a_time);
  389. #ifdef __GNUC__
  390. #ifndef __VERSION__
  391. #define __VERSION__ "[unknown]"
  392. #endif
  393.   fprintf (out, " # (META)compiled by GNU C version %s.\n", __VERSION__);
  394. #else
  395.   fprintf (out, " # (META)compiled by CC.\n");
  396. #endif
  397. }
  398.  
  399.                 /* DEBUGGING UTILITIES */
  400. rtx al_log_insn_debug;
  401.  
  402. abort_show_logged ()
  403. {
  404.   if (al_log_insn_debug)
  405.     my_print_rtx (al_log_insn_debug);
  406.   abort ();
  407. }
  408.  
  409. extern FILE *outfile;
  410.  
  411. void
  412. my_print_rtx (in_rtx)
  413.      register rtx in_rtx;
  414. {
  415.   FILE *old;
  416.   old = outfile;
  417.  
  418.   outfile = stderr;
  419.   print_rtx (in_rtx);
  420.   fprintf (outfile, "\n");
  421.  
  422.   outfile = old;
  423. }
  424.  
  425. void
  426. my_print_insncode (insn)
  427.      rtx insn;
  428. {
  429.   FILE *old;
  430.   old = outfile;
  431.  
  432.   outfile = stderr;
  433.   print_rtx (insn);
  434.   fprintf (outfile, "\n");
  435.   fprintf (outfile, "INSN_CODE (insn) = %X\n", INSN_CODE (insn));
  436.  
  437.   outfile = old;
  438. }
  439.  
  440. void
  441. abort_with_insn (insn, reason)
  442.      rtx insn;
  443.      char *reason;
  444. {
  445.   fprintf (stderr, "About to Abort::%s\n", reason);
  446.   my_print_rtx (insn);
  447.   abort ();
  448. }
  449. #endif
  450.  
  451. void
  452. abort_with_insn ()
  453. {
  454.   abort ();
  455. }
  456.  
  457. void
  458. my_print_rtx (in_rtx)
  459.      register rtx in_rtx;
  460.  
  461. {
  462.   abort();
  463. }
  464.  
  465. #include "tree.h"
  466.                 /* GET SECTION (DATA/SDATA) THRESHOLD */
  467. int mips_section_threshold = -1;
  468.  
  469. extern char *tree_code_name[];
  470.  
  471. int
  472. mips_section_get ()
  473. {
  474.   register int i;
  475.   if (mips_section_threshold == -1)
  476.     {
  477.       i = TARGET_GVALUE;
  478.       if (i >= 6) i += 3;
  479.       if ((1 << i) != MIPS_GVALUE_DEFAULT)
  480.     warning ("G value this run == %d\n", 1 << i);
  481.       mips_section_threshold = 1 << i;
  482.     }
  483.  
  484.   return mips_section_threshold;
  485. }
  486.  
  487. int
  488. mips_output_external (file, tree_exp, name)
  489.      FILE *file;
  490.      tree tree_exp;
  491.      char *name;
  492. {
  493.   register int i;
  494.   if (TARGET_GP_OPT
  495.       && ((TREE_CODE (tree_exp)) != FUNCTION_DECL)
  496.       &&
  497.       ((i = int_size_in_bytes (TREE_TYPE (tree_exp))) > 0))
  498.     {
  499.       fputs ("\n#ifndef _gccx__", file);
  500.       assemble_name (file, name);
  501.       fputs ("\n.extern\t", (file));
  502.       assemble_name ((file), (name));
  503.       fprintf ((file), ", %d", i, (TREE_TYPE (tree_exp)));
  504.       fputs ("\n#define _gccx__", file);
  505.       assemble_name (file, name);
  506.       fputs ("\n#endif\n ", file);
  507.     }
  508.   return 0;
  509. }
  510.  
  511. extern char *asm_file_name;
  512.  
  513. int
  514. mips_asm_file_end (file)
  515.      FILE *file;
  516. {
  517.   if (TARGET_GP_OPT)
  518.     {
  519.       fprintf (file, "\n#else\n#ifndef %sRESCAN_GCC", "__x_");
  520.       fprintf (file, "\n#define %sRESCAN_GCC\n#include \"%s\"", "__x_",
  521.            asm_file_name);
  522.       fprintf (file, "\n#endif\n#endif\n");
  523.     }
  524. }
  525.